package com.sy.musicapp.ui.common

import androidx.compose.animation.*
import androidx.compose.animation.core.MutableTransitionState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Card
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Add
import androidx.compose.material.icons.rounded.PlaylistAdd
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
import androidx.lifecycle.viewmodel.compose.viewModel
import coil.compose.rememberImagePainter
import com.sy.musicapp.model.Lyric
import com.sy.musicapp.model.Music
import com.sy.musicapp.model.MusicViewModel
import com.sy.musicapp.model.Playlist
import com.sy.musicapp.ui.theme.Global
import com.sy.musicapp.ui.theme.tintText
import java.text.SimpleDateFormat
import java.util.*


/**
 * 歌曲项
 * @param music
 * @param itemClick 点击播放
 * @param itemIconClick 下一首播放
 * @author SY
 * @since 2022/2/25 17:44
 */
@ExperimentalAnimationApi
@Composable
fun MusicListItem(
    music: Music,
    isShowImgOnDefault: Boolean = false,
    action: Music,
    icon: ImageVector = Icons.Rounded.Add,
    imgShape: Shape = Global.shapes.medium,
    itemClick: () -> Unit,
    itemIconClick: () -> Unit
) {
    val visibleState = remember { MutableTransitionState(initialState = false) }
    var isAction by remember {
        mutableStateOf(false)
    }
    isAction = action.id == music.id && music.isNext == action.isNext
    val color = if (isAction) Global.colors.secondary else Global.colors.onPrimary
    CommItem(
        leftContent = {
            AnimatedVisibility(visibleState = visibleState.apply {
                targetState = isShowImgOnDefault && !music.isNext
            }) {
                Image(
                    painter = rememberImagePainter(data = music.picUrl),
                    contentDescription = null,
                    modifier = Modifier
                        .keepSquare()
                        .padding(5.dp)
                        .clip(imgShape)
                )
            }
            if (music.isNext) {
                Icon(
                    imageVector = Icons.Rounded.PlaylistAdd,
                    contentDescription = null,
                    tint = Global.colors.onPrimary
                )
                Text(
                    text = music.name,
                    color = color,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.widthIn(max = 150.dp)
                )
            } else {
                Column(
                    verticalArrangement = Arrangement.spacedBy(5.dp)
                ) {
                    Text(
                        text = music.name,
                        color = color,
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis,
                        modifier = Modifier.widthIn(max = 130.dp)
                    )
                    Text(text = music.artist, style = tintText)
                }
            }
        },
        rightContent = {
//            Text(text = music.album)
            Icon(
                imageVector = icon,
                contentDescription = null,
                modifier = Modifier
                    .scale(0.9f)
                    .noRippleClickable {
                        itemIconClick()
                    },
                tint = Global.colors.onPrimary
            )
        },
        click = { itemClick() }
    )
}


/**
 * 歌单项
 * @param folder Item
 * @param itemClick 提供歌单名
 * @param itemDel 提供歌单id
 * @author SY
 * @since 2022/2/15 23:47
 */
@Composable
fun PlaylistItem(
    folder: Playlist,
    itemClick: (String) -> Unit,
    itemDel: (String) -> Unit
) {
    CommItem(
        leftContent = {
            Image(
                painter = rememberImagePainter(data = folder.coverImgUrl),
                contentDescription = null,
                modifier = Modifier
                    .keepSquare()
                    .clip(Global.shapes.medium)
            )
            Column(
                verticalArrangement = Arrangement.spacedBy(5.dp)
            ) {
                Text(text = folder.name, fontSize = 14.sp)
                Text(text = "${folder.trackCount}首", style = tintText)
            }
        },
        rightContent = {
//            Icon(
//                imageVector = Icons.Outlined.Delete,
//                contentDescription = null,
//                modifier = Modifier
//                    .scale(0.9f)
//                    .noRippleClickable {
//                        itemDel(folder.id)
//                    },
//                tint = Global.colors.onPrimary
//            )
            Text(
                text = SimpleDateFormat(
                    "yyyy-MM-dd",
                    Locale.SIMPLIFIED_CHINESE
                ).format(folder.createTime),
                style = tintText
            )
        },
        click = { itemClick(folder.id) }
    )
}


@Composable
fun CommItem(
    leftContent: @Composable () -> Unit,
    rightContent: @Composable () -> Unit,
    click: () -> Unit
) {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween,
        modifier = Modifier
            .fillMaxWidth(1f)
            .noRippleClickable { click() }
            .height(50.dp)
    ) {
        Row(
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(5.dp)
        ) {
            leftContent()
        }
        Row(
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(5.dp)
        ) {
            rightContent()
        }
    }
}


/**
 * @param title 卡片标题
 * @param littleContent 卡片功能菜单
 * @param content 卡片主体内容
 * @author SY
 * @since 2022/2/15 20:54
 */
@Composable
fun MyCard(
    title: String,
    littleContent: @Composable () -> Unit = {},
    content: @Composable () -> Unit
) {
    Card(
        modifier = Modifier.heightIn(Dp.Unspecified, 300.dp),
        backgroundColor = Global.colors.primary,
        elevation = 0.dp
    ) {
        Column(modifier = Modifier.padding(horizontal = 15.dp, vertical = 10.dp)) {
            Row(
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.SpaceBetween,
                modifier = Modifier
                    .fillMaxWidth(1f)
                    .padding(bottom = 0.dp)
            ) {
                Text(
                    text = title,
                    fontSize = 16.sp,
                    fontWeight = FontWeight.ExtraBold,
                    color = Global.colors.secondary
                )
                littleContent()
            }
            content()
        }
    }
}


/**
 * 自定义底部抽屉式动作条
 * @param visible 是否可见
 * @param maskColor 背景遮罩颜色
 * @param contentBackgroundColor 抽屉背景色
 * @param shapes 抽屉边角形状
 * @author SY
 * @since 2022/2/14 21:03
 */
@ExperimentalAnimationApi
@Composable
fun MyDrawer(
    visible: Boolean,
    model: MusicViewModel = viewModel(),
    maskColor: Color = Color.Transparent,
    contentBackgroundColor: Color = Global.colors.primary,
    shapes: Shape = RoundedCornerShape(topStart = 15.dp, topEnd = 15.dp),
    content: @Composable () -> Unit
) {
    AnimatedVisibility(
        visible = visible,
        enter = slideInVertically(initialOffsetY = { 2000 }),
        exit = slideOutVertically(targetOffsetY = { 2000 }),
        modifier = Modifier
            .zIndex(10f)
//            .navigationBarsPadding()
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize(1f)
                .background(maskColor)
                .noRippleClickable {
                    model.musicListShowChange()
                },
            verticalArrangement = Arrangement.Bottom
        ) {
            Box(
                modifier = Modifier
                    .fillMaxSize(1f, 0.5f)
                    .background(contentBackgroundColor, shapes)
                    .align(Alignment.End)
                    .noRippleClickable {},
                content = { content() }
            )
        }
    }
}

/**
 * 歌词 Item
 *
 * @param lyricsEntry 歌词 [Lyric]
 * @param current 是否为当前播放
 * @param textSize 字体大小
 * @param centerAlign 是否居中对齐
 */
@Composable
private fun LyricsItem(
    lyricsEntry: Lyric,
    current: Boolean = false,
    currentTextElementHeightPxState: MutableState<Int>,
    textSize: Int,
    centerAlign: Boolean = false,
    onClick: () -> Unit
) {
    val mainLyrics = lyricsEntry.text
    // 当前正在播放的歌词高亮
    val textAlpha = animateFloatAsState(if (current) 1F else 0.32F).value
    val color =
        animateColorAsState(if (current) Global.colors.secondary else Global.colors.onPrimary).value
    // 歌词文本对齐方式，可选左 / 中
    val align = if (centerAlign) TextAlign.Center else TextAlign.Left
    Card(
        modifier = Modifier
            .onSizeChanged {
                if (current) {
                    // 告知当前高亮歌词 Item 高度
                    currentTextElementHeightPxState.value = it.height
                }
            }
            .padding(0.dp, (textSize * 0.1F).dp),
        backgroundColor = Color.Transparent,
        elevation = 0.dp
    ) {
        val paddingY = (textSize * 0.3F).dp
        // 这里使用 Column 是为了若以后拓展具体显示
        Column(
            modifier = Modifier
                .noRippleClickable {
                    onClick()
                }
                .padding(8.dp, paddingY),
            verticalArrangement = Arrangement.Center
        ) {
            val mainTextSize = 16.sp
            Text(
                modifier = Modifier
                    .alpha(textAlpha),
                text = mainLyrics,
                fontSize = mainTextSize,
                color = color,
                textAlign = align
            )
        }
    }
}


@Composable
fun LyricView(
    modifier: Modifier,
    liveTime: Int = 0,
    lyricsEntryList: List<Lyric>?,
    textSize: Int = 20,
    paddingWidth: Dp = 30.dp,
    alignCenter: Boolean = false,
    itemOnClick: (Lyric) -> Unit,
) {
    val state = rememberLazyListState()
    // 当没歌词的时候
    if (lyricsEntryList == null || lyricsEntryList.isEmpty()) {
        Box(
            modifier = modifier
        ) {
            Text(
                text = "没有歌词",
                modifier = Modifier.align(Alignment.Center),
                color = Global.colors.onPrimary,
                fontSize = 16.sp
            )
        }
    } else {
        val currentTextElementHeightPx = remember { mutableStateOf(0) }
        BoxWithConstraints(
            modifier = modifier
        ) {
            // 前后空白
            val blackItem: (LazyListScope.() -> Unit) = {
                item {
                    Box(
                        modifier = Modifier
                            .height(maxHeight / 2)
                    ) {}
                }
            }
            var action by remember {
                mutableStateOf(0)
            }
            // 歌词主体
            val lyricsEntryListItems: (LazyListScope.() -> Unit) = {
                itemsIndexed(lyricsEntryList, { index, _ -> index }) { index, lyricsEntry ->
                    LyricsItem(
                        lyricsEntry = lyricsEntry,
                        current = action == index,
                        currentTextElementHeightPxState = currentTextElementHeightPx,
                        textSize = textSize,
                        centerAlign = alignCenter,
                    ) {
                        itemOnClick(lyricsEntry)
                    }
                }
            }
            LazyColumn(
                Modifier
                    .fillMaxWidth()
                    .fillMaxHeight()
                    .padding(paddingWidth, 0.dp)
                    .graphicsLayer { alpha = 0.99F }
                    .drawWithContent {
                        val colors = listOf(
                            Color.Transparent, Color.Black, Color.Black, Color.Black, Color.Black,
                            Color.Black, Color.Black, Color.Black, Color.Transparent
                        )
                        drawContent()
                        drawRect(
                            brush = Brush.verticalGradient(colors),
                            blendMode = BlendMode.DstIn
                        )
                    },
                state = state
            ) {
                blackItem()
                lyricsEntryListItems()
                blackItem()
            }

            // 定位中间
            LaunchedEffect(key1 = liveTime, key2 = currentTextElementHeightPx.value) {
//                val height = dpTopx(maxHeight.value) - currentTextElementHeightPx.value
                val height = maxHeight.value - currentTextElementHeightPx.value
                lyricsEntryList.forEachIndexed { i, lyric ->
                    try {
                        if (liveTime in (lyricsEntryList[i - 1].time..lyric.time))
                            action = i
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
                state.animateScrollToItem(action, (-height).toInt())
            }
        }
    }
}


@ExperimentalAnimationApi
@Composable
fun NavEnterAndExitAnimation(content: @Composable () -> Unit) {
    val visibleState = remember { MutableTransitionState(initialState = false) }
    AnimatedVisibility(
        visibleState = visibleState.apply {
            targetState = true
        },
        enter = slideInVertically(
            initialOffsetY = { -200 }
        ),
        exit = slideOutVertically() + shrinkVertically() + fadeOut(),
    ) {
        content()
    }
}